package com.pjb.springbootjjwt.store.storage;

import com.pjb.springbootjjwt.store.Defines;
import com.pjb.springbootjjwt.store.File;
import com.pjb.springbootjjwt.store.Sql;
import com.pjb.springbootjjwt.store.entity.*;
import com.pjb.springbootjjwt.store.server.AST;
import com.pjb.springbootjjwt.store.server.Query;
import com.pjb.springbootjjwt.store.utils.StringUtil;

import java.util.ArrayList;
import java.util.List;

public class DML {

    public static void main(String[] args) throws Exception {
        try {
//            String name = "vv";
            //new DML().delete("vv", "delete from vv");
            new DML().delete("mm", "delete from mm");
            for (int i = 0; i < 5; i++) {
                //String sql = "insert into vv('000"+ i +"', '2b', '3c')";
                //new DML().insert(name, sql);
                new DML().insert("mm", "insert into mm('000" + i + "')");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 插入数据
     *
     * @param table
     * @param sql
     * @throws Exception
     */
    public void insert(String table, String sql) throws Exception {
        Line line = new Line();
        List<String> data = Sql.getInstance().getValue(sql);
        line.setData(data);
        String ddl = File.getInstance().getDDL(table);
        String pk = Sql.getInstance().getPK(ddl);
        String id = StringUtil.uuid();
        if (pk != null) {
            int index = Sql.getInstance().getPKIndex(ddl);
            id = line.getData().get(index);
        }

        line.setKey(id);
        File.getInstance().add(table, line);
    }

    /**
     * 删除数据
     *
     * @param table
     * @param sql
     * @throws Exception
     */
    public void delete(String table, String sql) throws Exception {
        List<Line> list = Defines.getHandler(table).get(table).getLine();
        List<Line> subList = getClause(table, sql, list);
        Defines.getHandler(table).delete(table, list, subList);
    }

    public void update(String table, String sql) throws Exception {
        List<Line> list = Defines.getHandler(table).get(table).getLine();
        List<Line> subList = getClause(table, sql, list);
        List<Clause> clauses = Sql.getInstance().getSets(sql);
        for (Clause c : clauses) {
            int index = Sql.getInstance().getFieldIndexByTable(Table.toTable(table), c.getKey());
            updateByClause(subList, c.getValue(), index);
        }

        File.getInstance().update(table, list, subList);
    }

    private List<Line> getClause(String table, String sql, List<Line> list) throws Exception {
        List<Clause> clause = Sql.getInstance().getClause(sql);
        List<Line> subList = new ArrayList<>();
        if (clause != null) {
            subList = Query.getInstance().getList(Table.toTable(table), clause).getLine();
        } else {
            for (Line line : list) {
                subList.add(line);
            }
        }
        return subList;
    }

    private void updateByClause(List<Line> list, String clause, int index) {
        for (Line line : list) {
            line.getData().set(index, clause);
        }
    }

    public Record call(String sql) throws Exception {
        Record r = null;
        r = Query.getInstance().call(sql);
        Response.printQuery(r, sql);
        return r;
    }

    public Record fun(String sql) throws Exception {
        Record r = null;
        r = Query.getInstance().fun(sql);
        Response.printQuery(r, sql);
        return r;
    }

    public Record select(String sql) throws Exception {
        AST ast = new AST(sql);
        List<AST.Tree> trees = new ArrayList<>();
        ast.visit(ast.getRoot(), trees, "root");
        Record r = null;
        while (trees.size() > 0) {
            AST.Tree tree = trees.remove(trees.size() - 1);
            if (!tree.getValue().contains("@")) {
                r = Query.getInstance().select(tree.getValue());
            } else {
                r = Query.getInstance().select(tree, r);
            }
        }

        Response.printQuery(r, sql);
        return r;
    }
}
